/*
* This file is a part of the open-eBackup project.
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
* If a copy of the MPL was not distributed with this file, You can obtain one at
* http://mozilla.org/MPL/2.0/.
*
* Copyright (c) [2024] Huawei Technologies Co.,Ltd.
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*/
package openbackup.data.access.framework.protection.service.archive;

import com.huawei.oceanprotect.job.constants.JobExtendInfoKeys;

import lombok.extern.slf4j.Slf4j;
import openbackup.data.access.framework.core.common.constants.ContextConstants;
import openbackup.data.protection.access.provider.sdk.job.JobCallbackProvider;
import openbackup.system.base.common.model.job.JobBo;
import openbackup.system.base.common.utils.JSONObject;
import openbackup.system.base.common.utils.VerifyUtil;
import openbackup.system.base.sdk.job.model.JobTypeEnum;
import openbackup.system.base.security.exterattack.ExterAttack;

import org.redisson.api.RMap;
import org.redisson.api.RedissonClient;
import org.redisson.client.codec.StringCodec;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * 归档任务中止回调
 *
 */
@Slf4j
@Component
public class UnifiedArchiveJobCallbackProvider implements JobCallbackProvider {
    private static final int ABORTED = 3;

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private ArchiveClient archiveClient;

    @Override
    public boolean applicable(String jobType) {
        return JobTypeEnum.ARCHIVE.getValue().equals(jobType);
    }

    @ExterAttack
    @Override
    public void doCallback(JobBo job) {
        // 处理归档强制停止后未清理redis的队列
        log.info("Start to handle job callback, job:{}", job.getJobId());
        String requestId = JSONObject.fromObject(job.getExtendStr()).getString(ContextConstants.REQUEST_ID);
        if (VerifyUtil.isEmpty(requestId)) {
            oldJobHandle(job);
            return;
        }
        newJobHandle(job, requestId);
    }

    private void newJobHandle(JobBo job, String requestId) {
        log.info("Start to handle new job callback, job:{}", job.getJobId());
        JSONObject archiveRequest = new JSONObject();
        archiveRequest.put(ContextConstants.REQUEST_ID, requestId);
        archiveRequest.put(ArchiveContext.JOB_ID, job.getJobId());
        archiveRequest.put(ArchiveContext.STATUS, ABORTED);
        archiveRequest.put(ArchiveContext.ORIGINAL_COPY_ID_KEY, job.getCopyId());
        archiveRequest.put(ArchiveContext.AUTO_RETRY_TIMES, 0);
        archiveClient.archiveDone(archiveRequest.toString());
    }

    private void oldJobHandle(JobBo job) {
        log.info("Start to handle old job callback, job:{}", job.getJobId());
        RMap<String, String> map = redissonClient.getMap(job.getSourceId(), StringCodec.INSTANCE);
        if (VerifyUtil.isEmpty(map)) {
            log.info("Redis has no map:{}, skip call back!", job.getSourceId());
            return;
        }
        String storageId = JSONObject.fromObject(job.getExtendStr()).getString(JobExtendInfoKeys.STORAGE_ID);
        map.remove(storageId);
    }
}
